﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Forms;
using PSE.Deployment.SetupBase;
using PSE.Deployment.SetupBase.Configuration;
using PSE.Deployment.SetupBase.UI;
using PSE.Deployment.Util;
using PSE.Deployment.ConfigurationManager.Controls;
using System.Security.AccessControl;
using System.Security.Principal;

namespace PSE.Deployment.SetupBase.UI
{
    public partial class InstallationPath : BaseWizardWindow
    {
        #region Fields
        Int64 _freeDiskSpace = 0;
        Int64 _requiredDiskSpace = 0;
        string _driveName;
        private List<String> _computedItems = new List<string>();
        #endregion

        #region Construtor
        public InstallationPath()
        {
            this.InitializeComponent();

            // Insert code required on object creation below this point.
            LoadConfiguration();
            SetRequiredDiskSpace();
            CheckAllowNext();
        }
        #endregion

        private Int64 GetRequiredDiskSpace()
        {
            Int64 requiredDiskSpace = 0;

            List<Group> groups = SetupMainFactory.GetInstance().Parameter.SetupConfiguration.SystemInfo.Groups.
                SelectDeep(g => g.SubGroups).SelectDeep(g => g.Dependencies).Where(g => (g.Install == null || g.Install.GetValueOrDefault()) && !g.Installed).Distinct(new GroupComparer()).ToList();

            foreach (Group group in groups)
            {
                foreach (ActionBase action in group.Actions)
                {
                    if (action is PSE.Deployment.SetupBase.Configuration.Actions.Copy)
                    {
                        foreach (FolderInfo folderInfo in ((PSE.Deployment.SetupBase.Configuration.Actions.Copy)action).Folders)
                        {
                            string path = Path.Combine(SetupMainFactory.GetInstance().Parameter.InstalationSource, folderInfo.Source);

                            if (folderInfo.Files.Count == 0)
                            {
                                requiredDiskSpace += PSE.Deployment.Util.File.CalculateFolderSize(path);
                            }
                            else
                            {
                                requiredDiskSpace += PSE.Deployment.Util.File.CalculateFilesSize(folderInfo.Files.ToArray());
                            }
                        }
                    }
                }
            }

            return requiredDiskSpace;
        }

        #region Métodos de comparação e exibição do espaço requerido e disponível
        private void SetRequiredDiskSpace()
        {
            _requiredDiskSpace = GetRequiredDiskSpace();

            TxtRequiredDiskSpace.Text = "Espaço Requerido: " + ConvertDiskSpaceSize(_requiredDiskSpace);
        }

        private void CheckAllowNext()
        {
            this.AllowNext = !(_freeDiskSpace < _requiredDiskSpace);
            SetStatus();
        }

        private void SetStatus()
        {
            if (_freeDiskSpace < _requiredDiskSpace)
            {
                ImgStatusError.Visibility = Visibility.Visible;
                ImgStatusOk.Visibility = Visibility.Collapsed;
            }
            else
            {
                ImgStatusError.Visibility = Visibility.Collapsed;
                ImgStatusOk.Visibility = Visibility.Visible;
            }
        }

        private void SetFreeSpace()
        {
            DriveInfo driveInfo = new DriveInfo(txtCaminhoInstalacao.Text);
            _freeDiskSpace = 0;
            _driveName = string.Empty;

            if (CheckDirectoryAccess(txtCaminhoInstalacao.Text))//TODO:adicionar verificacao de permissao de acesso
            {
                _driveName = driveInfo.Name;
                _freeDiskSpace = driveInfo.TotalFreeSpace;
            }
            else
            {
                ConfigurationMessageBox.Show("O diretório selecionado não pode ser utilizado. Selecione um outro diretório para continuar a instalação.", "Atenção", ConfigurationMessageBoxButton.Ok, ConfigurationMessageBoxImage.Exclamation);
            }


            txtFreeDiskSpace.Text = "Espaço livre na unidade selecionada: " + ConvertDiskSpaceSize(_freeDiskSpace);

        }

        /// <summary>
        /// Verificar o acesso de escrita em um diretorio
        /// </summary>
        /// <param name="directory"></param>
        /// <returns></returns>
        private bool CheckDirectoryAccess(string directory)
        {
            try
            {
                //se o diretorio ja existir
                if (Directory.Exists(directory))
                {
                    //tentar criar e excluir um arquivo
                    System.IO.File.CreateText(Path.Combine(directory, "write.chk")).Close();
                    System.IO.File.Delete(Path.Combine(directory, "write.chk"));
                }
                //caso n exista o diretorio
                else
                {
                    //tentar criar e excluir o diretorio
                    Directory.CreateDirectory(directory).Delete();
                }
                return true;
            }
            catch
            {
                return false;
            }
        }

        #endregion

        #region Métodos de Load e Save dos Caminhos de Instalação
        private void LoadConfiguration()
        {
            txtCaminhoInstalacao.Text = SetupMainFactory.GetInstance().Parameter.InstallationPath;

            SetFreeSpace();
        }

        private void SaveInstallationPath()
        {
            SetupMainFactory.GetInstance().Parameter.InstallationPath = txtCaminhoInstalacao.Text;
            SetupMainFactory.GetInstance().Parameter.FullInstallationPath = Path.Combine(txtCaminhoInstalacao.Text, SetupMainFactory.GetInstance().SystemId);
        }
        #endregion

        #region Método para exibição da janela para seleção do caminho de instalação
        private void ShowFileDialog()
        {
            FolderBrowserDialog fbd = new FolderBrowserDialog();
            fbd.Description = "Escolha o caminho para instalação do Sistema";
            fbd.ShowNewFolderButton = true;
            fbd.SelectedPath = txtCaminhoInstalacao.Text;

            if (fbd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                txtCaminhoInstalacao.Text = fbd.SelectedPath + @"\";
            }

            fbd.Dispose();

        }
        #endregion

        #region Evento do Botão para selecionar o caminho de instalação de Serviços e User Interface

        private void BtnSelectPath_Click(object sender, RoutedEventArgs e)
        {
            ShowFileDialog();
            SetFreeSpace();
            CheckAllowNext();
        }

        #endregion

        #region Método de conversão do tamanho em bytes para KB, MB ou GB
        private string ConvertDiskSpaceSize(Int64 size)
        {
            double convertedSize = Convert.ToDouble(size);
            int i = 0;
            string measure = "MB";

            while (convertedSize / 1024 >= 1
                && i < 4)
            {
                convertedSize = convertedSize / 1024;
                i++;
            }

            switch (i)
            {
                case (0):
                    measure = "MB";
                    break;
                case (1):
                    measure = "KB";
                    break;
                case (2):
                    measure = "MB";
                    break;
                case (3):
                    measure = "GB";
                    break;
            }

            return String.Concat(Math.Round(convertedSize, 2).ToString(), " ", measure);
        }
        #endregion

        #region Eventos dos Botões Próximo e Anterior
        protected override void OnNextClick(RoutedEventArgs e)
        {
            base.OnNextClick(e);
            SaveInstallationPath();
        }

        protected override void OnPreviousClick(RoutedEventArgs e)
        {
            base.OnPreviousClick(e);
            SaveInstallationPath();
        }
        #endregion

    }

    public enum DependencyType
    {
        Source,
        Dependency
    }
}
